#ifndef MY_SHELL_GRAMMAR_NODE_H
#define MY_SHELL_GRAMMAR_NODE_H

#include <vector>
#include <string>
#include <cstdint>
#include <memory>

#include "MyShellNamespace.h"
#include "MyShellWord.h"

MY_SHELL_NAMESPACE_BEGIN
// 语法节点类型
enum GRAMMAR_NODE_TYPE {
    ILLEGAL_GRAMMAR, 
    DECLARE_STATEMENT, 
    RUN_STATEMENT, 
    INPUT_STATEMENT, 
    OUTPUT_STATEMENT, 
    LEFT_VALUE_NODE, 
    DATA_NODE, 
    ASSIGN_STATEMENT, 
    FOR_TO_BLOCK, 
    FOR_IN_BLOCK, 
    IF_ELSE_BLOCK, 
    CALL_STATEMENT, 
    RETURN_STATEMENT, 
    FUNCTION_STATEMENT
};

// 语法节点
class GrammarNode
{
public:
    // 语法节点类型
    mysh::GRAMMAR_NODE_TYPE grammar_node_type;
public:
    // 构造函数及析构函数
    GrammarNode(mysh::GRAMMAR_NODE_TYPE grammar_node_type = mysh::ILLEGAL_GRAMMAR);
    virtual ~GrammarNode() {};
};

// declare语句
class DeclareStatementNode: public GrammarNode
{
public:
    // 标识符的数据类型
    mysh::WORD_TYPE data_type;
    // 标识符列表
    std::vector<std::string> identifiers;
    // 维度(非数组类型的数据维度为0)
    std::int32_t dimension;
    // 每个维度的大小
    std::vector<std::size_t> size_of_every_demension;
public:
    // 构造函数及析构函数
    DeclareStatementNode(mysh::WORD_TYPE data_type, const std::vector<std::string>& identifiers, const std::int32_t& dimension, const std::vector<std::size_t>& size_of_every_demension);
    ~DeclareStatementNode() override {};
};

// run语句节点
class RunStatementNode: public GrammarNode
{
public:
    // 参数列表，用于替换command中的井号
    std::vector<mysh::Word> param_list;
    // 运行命令语句的返回类型
    mysh::WORD_TYPE data_type;
    // 返回值的维度(非数组类型的数据维度为0)
    std::int32_t dimension;
    // 每个维度的大小
    std::vector<std::size_t> size_of_every_demension;
    // 所需运行的命令
    std::string command;
public:
    // 构造函数及析构函数
    RunStatementNode(
        const std::vector<mysh::Word>& param_list, 
        mysh::WORD_TYPE data_type, 
        const std::int32_t& dimension, 
        const std::vector<std::size_t>& size_of_every_demension, 
        const std::string& command
    );
    ~RunStatementNode() override {};
};

// input或output语句节点
class InputOutputStatementNode: public mysh::GrammarNode
{
public:
    // 输入输出所需要的标识符
    std::string identifier;
public:
    // 构造函数及析构函数
    InputOutputStatementNode(bool input_output, const std::string& identifier);
    ~InputOutputStatementNode() override {};
};

// 左值语法节点
class LeftValueNode: public GrammarNode
{
public:
    // 标识符
    std::string identifier;
    // 各维度编号
    std::vector<mysh::Word> index;
public:
    // 构造函数及析构函数
    LeftValueNode(const std::string& identifier, const std::vector<mysh::Word>& index);
    ~LeftValueNode() override {};
};

// 数值语法节点
class DataNode: public GrammarNode
{
public:
    // 数值类型
    mysh::WORD_TYPE data_type;
    // 数值(用字符串存储，之后在解析)
    std::string value;
public:
    // 构造及析构函数
    DataNode(mysh::WORD_TYPE data_type, const std::string& value);
    ~DataNode() override {};
};

// assign语句
class AssignStatementNode: public GrammarNode
{
public:
    // 赋值号左边的左值节点
    std::shared_ptr<mysh::LeftValueNode> left_value;
    // 赋值号右边的表达式节点
    std::shared_ptr<mysh::GrammarNode> expression;
public:
    // 构造函数及析构函数
    AssignStatementNode(const std::shared_ptr<mysh::LeftValueNode>& left_value, const std::shared_ptr<mysh::GrammarNode>& expression);
    ~AssignStatementNode() override {};
};

// if-else语句块
class IfElseStatementBlock: public GrammarNode
{
public:
    // 每个分支的条件语句
    std::vector<std::shared_ptr<mysh::GrammarNode>> conditions;
    // 每个分支的所有语句
    std::vector<std::vector<std::shared_ptr<mysh::GrammarNode>>> statements;
public:
    // 构造函数及析构函数
    IfElseStatementBlock(
        const std::vector<std::shared_ptr<mysh::GrammarNode>>& conditions, 
        const std::vector<std::vector<std::shared_ptr<mysh::GrammarNode>>>& statements
    );
    ~IfElseStatementBlock() override {};
};

// for-to循环语句块
class ForToStatementBlock: public GrammarNode
{
public:
    // to关键字前的节点
    std::shared_ptr<mysh::GrammarNode> node_before_to;
    // to关键字后的节点
    std::shared_ptr<mysh::GrammarNode> node_after_to;
    // for-to循环体内的语句
    std::vector<std::shared_ptr<mysh::GrammarNode>> statements;
public:
    // 构造函数及析构函数
    ForToStatementBlock(
        const std::shared_ptr<mysh::GrammarNode>& node_before_to, 
        const std::shared_ptr<mysh::GrammarNode>& node_after_to, 
        const std::vector<std::shared_ptr<mysh::GrammarNode>>& statements
    );
    ~ForToStatementBlock() override {};
};

// for-in循环语句节点
class ForInStatementBlock: public GrammarNode
{
public:
    // in关键字前的节点
    std::shared_ptr<mysh::GrammarNode> node_before_in;
    // in关键字后的节点
    std::shared_ptr<mysh::GrammarNode> node_after_in;
    // for-in循环体内的语句
    std::vector<std::shared_ptr<mysh::GrammarNode>> statements;
public:
    // 构造函数及析构函数
    ForInStatementBlock(
        const std::shared_ptr<mysh::GrammarNode>& node_before_in, 
        const std::shared_ptr<mysh::GrammarNode>& node_after_in, 
        const std::vector<std::shared_ptr<mysh::GrammarNode>>& statements
    );
    ~ForInStatementBlock() override {};
};

// call语句节点
class CallStatementNode: public GrammarNode
{
public:
    // 所调用的函数名
    std::string function_name;
    // 参数列表
    std::vector<mysh::Word> params;
public:
    // 构造函数及析构函数
    CallStatementNode(const std::string& function_name, const std::vector<mysh::Word>& params);
    ~CallStatementNode() override {};
};

// return语句节点
class ReturnStatementNode: public GrammarNode
{
public:
    // 返回的数据
    mysh::Word return_value;
public:
    // 构造函数及析构函数
    ReturnStatementNode(const mysh::Word& return_value);
    ~ReturnStatementNode() override {};
};

// function语句节点
class FunctionStatementNode: public GrammarNode
{
public:
    // 函数名
    std::string function_name;
    // 参数类型列表
    std::vector<mysh::WORD_TYPE> params_type_list;
    // 返回类型
    mysh::WORD_TYPE return_type;
    // 函数内语句
    std::vector<mysh::GrammarNode> statements;
public:
    // 构造函数及析构函数
    FunctionStatementNode(
        const std::string& function_name, 
        const std::vector<mysh::WORD_TYPE>& params_type_list, 
        mysh::WORD_TYPE return_type, 
        const std::vector<mysh::GrammarNode>& statements
    );
    ~FunctionStatementNode() override {};
};
MY_SHELL_NAMESPACE_END

#endif // ! MY_SHELL_GRAMMAR_NODE_H